#include <gtest/gtest.h>
#include <gmock/gmock.h>
#include "WTSContractInfo.hpp"
#include "WTSSessionInfo.hpp"
#include "WTSTradeDef.hpp"
#include "WTSDataDef.hpp"
#include <fstream>
#include <filesystem>
#include <thread>
#include <chrono>

using namespace wtp;

/*!
 * \brief WTS数据结构测试套件
 * 
 * \details 测试WTS相关数据结构的核心功能，包括：
 *          - 合约信息数据结构
 *          - 商品信息数据结构
 *          - 交易时段信息数据结构
 *          - 数据定义和类型验证
 *          - 内存管理和资源清理
 *          - 多线程安全性
 *          - 错误处理和边界条件
 */
class WTSDataStructureTest : public ::testing::Test {
protected:
    void SetUp() override {
        // 创建测试目录
        test_dir = "test_data_structure";
        std::filesystem::create_directories(test_dir);
    }
    
    void TearDown() override {
        // 清理测试文件
        std::filesystem::remove_all(test_dir);
    }
    
    std::string test_dir;
};

/*!
 * \brief 测试合约信息数据结构
 * 
 * \details 验证WTSContractInfo的基本功能：
 *          - 合约信息创建和初始化
 *          - 属性设置和获取
 *          - 内存管理
 */
TEST_F(WTSDataStructureTest, TestContractInfo) {
    // 测试合约信息创建
    WTSContractInfo* contract = WTSContractInfo::create("au2412", "黄金2412", "SHFE", "au");
    ASSERT_NE(contract, nullptr);
    
    // 测试基本属性
    EXPECT_STREQ(contract->getCode(), "au2412");
    EXPECT_STREQ(contract->getName(), "黄金2412");
    EXPECT_STREQ(contract->getExchg(), "SHFE");
    EXPECT_STREQ(contract->getProduct(), "au");
    
    // 测试完整代码
    EXPECT_STREQ(contract->getFullCode(), "SHFE.au2412");
    
    // 测试引用计数
    EXPECT_EQ(contract->retainCount(), 1);
    contract->retain();
    EXPECT_EQ(contract->retainCount(), 2);
    contract->release();
    EXPECT_EQ(contract->retainCount(), 1);
    
    // 最终释放
    contract->release();
}

/*!
 * \brief 测试商品信息数据结构
 * 
 * \details 验证WTSCommodityInfo的基本功能：
 *          - 商品信息创建和初始化
 *          - 属性设置和获取
 *          - 价格精度处理
 */
TEST_F(WTSDataStructureTest, TestCommodityInfo) {
    // 测试商品信息创建
    WTSCommodityInfo* commodity = WTSCommodityInfo::create("au", "黄金", "SHFE", "TRADING", "CHINA", "CNY");
    ASSERT_NE(commodity, nullptr);
    
    // 测试基本属性
    EXPECT_STREQ(commodity->getProduct(), "au");
    EXPECT_STREQ(commodity->getName(), "黄金");
    EXPECT_STREQ(commodity->getExchg(), "SHFE");
    EXPECT_STREQ(commodity->getCurrency(), "CNY");
    EXPECT_STREQ(commodity->getSession(), "TRADING");
    EXPECT_STREQ(commodity->getTradingTpl(), "CHINA");
    
    // 测试完整代码
    EXPECT_STREQ(commodity->getFullPid(), "SHFE.au");
    
    // 测试设置价格精度
    commodity->setPriceTick(0.02);
    EXPECT_DOUBLE_EQ(commodity->getPriceTick(), 0.02);
    
    // 测试设置合约乘数
    commodity->setVolScale(1000);
    EXPECT_EQ(commodity->getVolScale(), 1000);
    
    // 测试引用计数
    EXPECT_EQ(commodity->retainCount(), 1);
    
    // 释放资源
    commodity->release();
}

/*!
 * \brief 测试交易时段信息数据结构
 * 
 * \details 验证WTSSessionInfo的基本功能：
 *          - 交易时段创建和初始化
 *          - 时段属性设置和获取
 *          - 时间范围验证
 */
TEST_F(WTSDataStructureTest, TestSessionInfo) {
    // 测试交易时段创建
    WTSSessionInfo* session = WTSSessionInfo::create("TRADING", "交易时段", 0);
    ASSERT_NE(session, nullptr);
    
    // 测试基本属性
    EXPECT_STREQ(session->id(), "TRADING");
    EXPECT_STREQ(session->name(), "交易时段");
    EXPECT_EQ(session->getOffsetMins(), 0);
    
    // 测试添加交易时段
    session->addTradingSection(900, 1130);  // 09:00-11:30
    session->addTradingSection(1330, 1500); // 13:30-15:00
    
    // 验证交易时段数量
    EXPECT_EQ(session->getSectionCount(), 2);
    
    // 测试时间验证
    EXPECT_TRUE(session->isInTradingTime(1000));  // 10:00 在交易时间内
    EXPECT_FALSE(session->isInTradingTime(1200)); // 12:00 不在交易时间内
    EXPECT_TRUE(session->isInTradingTime(1400));  // 14:00 在交易时间内
    
    // 释放资源
    session->release();
}

/*!
 * \brief 测试数据定义和枚举值
 * 
 * \details 验证WTS数据类型的枚举定义：
 *          - K线周期枚举值
 *          - 交易方向枚举值
 *          - 订单状态枚举值
 */
TEST_F(WTSDataStructureTest, TestDataDefinitions) {
    // 测试K线周期枚举 - 这些是连续的整数值
    EXPECT_EQ(KP_Tick, 0);
    EXPECT_EQ(KP_Minute1, 1);
    EXPECT_EQ(KP_Minute5, 2);  // 实际值是2，不是5
    EXPECT_EQ(KP_DAY, 3);      // 实际值是3，不是1440
    
    // 测试交易方向枚举 - 这些是字符值
    EXPECT_EQ(WDT_LONG, '0');   // 实际值是字符'0'，不是数字1
    EXPECT_EQ(WDT_SHORT, '1');  // 实际值是字符'1'，不是数字-1
    
    // 测试订单状态枚举
    EXPECT_NE(WOS_NotTraded_Queuing, WOS_AllTraded);
    EXPECT_NE(WOS_PartTraded_Queuing, WOS_Canceled);
}

/*!
 * \brief 测试商品信息的高级功能
 * 
 * \details 验证WTSCommodityInfo的高级功能：
 *          - 交易模式设置
 *          - 合约类别设置
 *          - 平仓模式设置
 */
TEST_F(WTSDataStructureTest, TestCommodityAdvancedFeatures) {
    WTSCommodityInfo* commodity = WTSCommodityInfo::create("IF", "沪深300股指期货", "CFFEX", "TRADING", "CHINA", "CNY");
    ASSERT_NE(commodity, nullptr);
    
    // 测试交易模式设置
    commodity->setTradingMode(TM_Both);
    EXPECT_EQ(commodity->getTradingMode(), TM_Both);
    EXPECT_TRUE(commodity->canShort());
    EXPECT_FALSE(commodity->isT1());
    
    // 测试合约类别设置
    commodity->setCategory(CC_Future);
    EXPECT_EQ(commodity->getCategoty(), CC_Future);
    EXPECT_TRUE(commodity->isFuture());
    EXPECT_FALSE(commodity->isStock());
    EXPECT_FALSE(commodity->isOption());
    
    // 测试平仓模式设置
    commodity->setCoverMode(CM_CoverToday);
    EXPECT_EQ(commodity->getCoverMode(), CM_CoverToday);
    
    // 测试价格模式设置
    commodity->setPriceMode(PM_Both);
    EXPECT_EQ(commodity->getPriceMode(), PM_Both);
    
    // 测试最小手数设置
    commodity->setMinLots(1.0);
    EXPECT_DOUBLE_EQ(commodity->getMinLots(), 1.0);
    
    commodity->setLotsTick(1.0);
    EXPECT_DOUBLE_EQ(commodity->getLotsTick(), 1.0);
    
    commodity->release();
}

/*!
 * \brief 测试合约信息的高级功能
 * 
 * \details 验证WTSContractInfo的高级功能：
 *          - 交易量限制设置
 *          - 商品信息关联
 */
TEST_F(WTSDataStructureTest, TestContractAdvancedFeatures) {
    WTSContractInfo* contract = WTSContractInfo::create("IF2412", "沪深300股指期货2412", "CFFEX", "IF");
    ASSERT_NE(contract, nullptr);
    
    // 测试交易量限制设置
    contract->setVolumeLimits(1000, 5000);
    EXPECT_EQ(contract->getMaxMktVol(), 1000);
    EXPECT_EQ(contract->getMaxLmtVol(), 5000);
    
    // 测试商品信息关联
    WTSCommodityInfo* commodity = WTSCommodityInfo::create("IF", "沪深300股指期货", "CFFEX", "TRADING", "CHINA", "CNY");
    contract->setCommInfo(commodity);
    
    // 验证关联关系
    EXPECT_STREQ(contract->getProduct(), commodity->getProduct());
    EXPECT_STREQ(contract->getExchg(), commodity->getExchg());
    
    commodity->release();
    contract->release();
}

/*!
 * \brief 测试数据结构的内存管理
 * 
 * \details 验证数据结构的内存管理机制：
 *          - 引用计数机制
 *          - 自动释放机制
 *          - 内存泄漏检测
 */
TEST_F(WTSDataStructureTest, TestMemoryManagement) {
    std::vector<WTSContractInfo*> contracts;
    
    // 创建多个合约对象
    for (int i = 0; i < 100; ++i) {
        std::string code = "au" + std::to_string(2412 + i);
        std::string name = "黄金" + std::to_string(2412 + i);
        
        WTSContractInfo* contract = WTSContractInfo::create(code.c_str(), name.c_str(), "SHFE", "au");
        ASSERT_NE(contract, nullptr);
        contracts.push_back(contract);
    }
    
    // 验证所有对象都被正确创建
    EXPECT_EQ(contracts.size(), 100);
    
    // 验证引用计数
    for (auto* contract : contracts) {
        EXPECT_EQ(contract->retainCount(), 1);
        
        // 增加引用计数
        contract->retain();
        EXPECT_EQ(contract->retainCount(), 2);
    }
    
    // 释放所有对象
    for (auto* contract : contracts) {
        contract->release(); // 减少到1
        contract->release(); // 减少到0，对象被销毁
    }
}

/*!
 * \brief 测试多线程安全性
 * 
 * \details 验证数据结构在多线程环境下的安全性：
 *          - 并发创建对象
 *          - 并发访问对象
 *          - 线程安全的引用计数
 */
TEST_F(WTSDataStructureTest, TestThreadSafety) {
    const int num_threads = 10;
    const int objects_per_thread = 50;
    std::vector<std::thread> threads;
    std::vector<std::vector<WTSContractInfo*>> thread_objects(num_threads);
    
    // 启动多个线程并发创建对象
    for (int i = 0; i < num_threads; ++i) {
        threads.emplace_back([&, i]() {
            for (int j = 0; j < objects_per_thread; ++j) {
                std::string code = "au" + std::to_string(i * 1000 + j);
                std::string name = "黄金" + std::to_string(i * 1000 + j);
                
                WTSContractInfo* contract = WTSContractInfo::create(code.c_str(), name.c_str(), "SHFE", "au");
                ASSERT_NE(contract, nullptr);
                thread_objects[i].push_back(contract);
            }
        });
    }
    
    // 等待所有线程完成
    for (auto& t : threads) {
        t.join();
    }
    
    // 验证所有对象都被正确创建
    for (int i = 0; i < num_threads; ++i) {
        EXPECT_EQ(thread_objects[i].size(), objects_per_thread);
        for (auto* contract : thread_objects[i]) {
            ASSERT_NE(contract, nullptr);
            EXPECT_EQ(contract->retainCount(), 1);
        }
    }
    
    // 清理资源
    for (int i = 0; i < num_threads; ++i) {
        for (auto* contract : thread_objects[i]) {
            contract->release();
        }
    }
}

/*!
 * \brief 测试错误处理和边界条件
 * 
 * \details 验证数据结构的错误处理能力：
 *          - 无效参数处理
 *          - 空指针处理
 *          - 边界值处理
 */
TEST_F(WTSDataStructureTest, TestErrorHandling) {
    // 测试空字符串参数创建合约
    WTSContractInfo* contract1 = WTSContractInfo::create("", "测试合约", "SHFE", "au");
    if (contract1) {
        EXPECT_STREQ(contract1->getCode(), "");
        contract1->release();
    }
    
    // 注意：不要传递nullptr给create函数，这可能导致段错误
    // 而是测试其他边界条件
    
    // 测试空交易所参数
    WTSContractInfo* contract3 = WTSContractInfo::create("au2412", "黄金2412", "", "au");
    if (contract3) {
        EXPECT_STREQ(contract3->getExchg(), "");
        contract3->release();
    }
    
    // 测试空产品代码参数
    WTSContractInfo* contract4 = WTSContractInfo::create("au2412", "黄金2412", "SHFE", "");
    if (contract4) {
        EXPECT_STREQ(contract4->getProduct(), "");
        contract4->release();
    }
    
    // 测试商品信息的边界条件
    WTSCommodityInfo* commodity = WTSCommodityInfo::create("", "", "", "", "", "");
    if (commodity) {
        // 验证空参数不会导致崩溃
        EXPECT_TRUE(commodity->getProduct() != nullptr);
        commodity->release();
    }
}

/*!
 * \brief 测试性能特性
 * 
 * \details 验证数据结构的性能特性：
 *          - 创建性能
 *          - 访问性能
 *          - 内存使用效率
 */
TEST_F(WTSDataStructureTest, TestPerformanceCharacteristics) {
    const int num_objects = 10000;
    
    // 测试创建性能
    auto start = std::chrono::high_resolution_clock::now();
    
    std::vector<WTSContractInfo*> contracts;
    contracts.reserve(num_objects);
    
    for (int i = 0; i < num_objects; ++i) {
        std::string code = "au" + std::to_string(i);
        std::string name = "黄金" + std::to_string(i);
        
        WTSContractInfo* contract = WTSContractInfo::create(code.c_str(), name.c_str(), "SHFE", "au");
        ASSERT_NE(contract, nullptr);
        contracts.push_back(contract);
    }
    
    auto end = std::chrono::high_resolution_clock::now();
    auto create_duration = std::chrono::duration_cast<std::chrono::milliseconds>(end - start);
    
    std::cout << "创建 " << num_objects << " 个合约对象耗时: " << create_duration.count() << "ms" << std::endl;
    
    // 性能应该在合理范围内（小于1秒）
    EXPECT_LT(create_duration.count(), 1000);
    
    // 测试访问性能
    start = std::chrono::high_resolution_clock::now();
    
    std::string all_codes;
    for (auto* contract : contracts) {
        all_codes += contract->getCode();
        all_codes += contract->getExchg();
        all_codes += contract->getProduct();
    }
    
    end = std::chrono::high_resolution_clock::now();
    auto access_duration = std::chrono::duration_cast<std::chrono::microseconds>(end - start);
    
    std::cout << "访问 " << num_objects << " 个合约对象耗时: " << access_duration.count() << "μs" << std::endl;
    
    // 访问性能应该很快（小于10ms）
    EXPECT_LT(access_duration.count(), 10000);
    
    // 清理资源
    for (auto* contract : contracts) {
        contract->release();
    }
}

/*!
 * \brief 测试完整的数据结构工作流程
 * 
 * \details 验证数据结构的完整使用流程：
 *          - 创建 -> 设置属性 -> 使用 -> 释放
 */
TEST_F(WTSDataStructureTest, TestCompleteWorkflow) {
    // 1. 创建交易时段
    WTSSessionInfo* session = WTSSessionInfo::create("TRADING", "日盘交易", 0);
    ASSERT_NE(session, nullptr);
    
    // 2. 设置交易时段
    session->addTradingSection(900, 1130);   // 09:00-11:30
    session->addTradingSection(1330, 1500);  // 13:30-15:00
    
    // 3. 创建商品信息
    WTSCommodityInfo* commodity = WTSCommodityInfo::create("au", "黄金", "SHFE", "TRADING", "CHINA", "CNY");
    ASSERT_NE(commodity, nullptr);
    
    // 4. 设置商品属性
    commodity->setPriceTick(0.02);
    commodity->setVolScale(1000);
    commodity->setTradingMode(TM_Both);
    commodity->setCategory(CC_Future);
    commodity->setSessionInfo(session);
    
    // 5. 创建合约信息
    WTSContractInfo* contract = WTSContractInfo::create("au2412", "黄金2412", "SHFE", "au");
    ASSERT_NE(contract, nullptr);
    
    // 6. 设置合约属性
    contract->setVolumeLimits(1000, 5000);
    contract->setCommInfo(commodity);
    
    // 7. 验证关联关系
    EXPECT_STREQ(contract->getProduct(), commodity->getProduct());
    EXPECT_STREQ(contract->getExchg(), commodity->getExchg());
    
    // 8. 使用数据进行业务逻辑
    bool is_trading_time = session->isInTradingTime(1000); // 10:00
    EXPECT_TRUE(is_trading_time);
    
    std::string full_code = contract->getFullCode();
    EXPECT_EQ(full_code, "SHFE.au2412");
    
    double price_tick = commodity->getPriceTick();
    EXPECT_DOUBLE_EQ(price_tick, 0.02);
    
    bool can_short = commodity->canShort();
    EXPECT_TRUE(can_short);
    
    // 9. 释放资源
    session->release();
    commodity->release();
    contract->release();
    
    std::cout << "数据结构完整工作流程测试通过" << std::endl;
}